基于Elasticsearch如何实现一个好用的用户名检索?
先说一下背景,需要提供一个检索接口,根据用户输入的值去检索:姓名、姓名拼音、工号、昵称等。
迭代过的版本:
- 标准分词
- 中文支持不好
- wildcard type
- 因为有安全考虑,所以限制了总的返回条数为10,导致完整匹配的不是在前10条
- 这里还遇到了一个坑,华为云elasticsearch是基于OpenSearch的,不支持wildcard这种类型
关于姓名这个,由于大多数用户的姓名是汉字,所以第一个想到的是ik
IK方案
构建Dockerfile
1 | FROM registry.jiankunking.com/library/elasticsearch:7.13.4 |
IK插件已经上传到代码中,所有没有采用在线安装的方式
已将姓名字典放置到 elasticsearch-analysis-ik-7.13.4/config/custom_user_name.dic
IKAnalyzer.cfg.xml也已修改
1 | <?xml version="1.0" encoding="UTF-8"?> |
验证
模版
1 | POST /_template/jiankunking-attr |
查询验证过程略
结论
1、需要自定义词库
使用IK插件但不自定义词库的话,无法正确的分词姓名;
使用词库的话,需要穷举可能得搜索项,
假如,词典中只加载姓名,那么对于搜索后半段,比如:孙新伟,搜索:新伟,会搜索不到,这时候搜索结果就会不符合预期。
2、对于英文姓名分词有一定限制
比如搜索:dam,Adam Dean不会被检索到
3、需要安装IK插件,需要重启集群
Ngram方案
验证
模版
1 | POST /_template/jiankunking-attr-ngram |
查询验证过程略
结论
搜索返回的数据中,会有相似数据
比如搜索:”土豆儿”,会匹配到:”王豆豆”、”田豆豆”等
Ngram分词会消耗大量资源(尤其是磁盘),reindex有可能会超时
结论
由于用户数据量不到100万,所以即使资源效果的多一些,也在可以接受的范围内,所以最终采取了Ngram方案
最优的查询语句如下:
1 | { |